package com.filldream.fastboot.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 集合工具类
 * @author RickSun && iFillDream
 */
@Slf4j
public class ListUtil {

	/**
	 * 排序基础List
	 * <p>List元素不能为Bean,否则报错<p/>
	 * @param list
	 * @param isAsc true-升序 false-降序
	 * @param <T>
	 * @return
	 */
	private static <T> List<T>  sortBase(List<T> list,Boolean isAsc){
		List<T> result = list.stream().sorted().collect(Collectors.toList());
		if(!isAsc){
			Collections.reverse(result);
		}
		return result;
	}

	/**
	 * 去除基础List重复值
	 * <p>若List元素为Bean,则去除对象属性值一致的重复对象<p/>
	 * @param list
	 * @param <T>
	 * @return
	 */
	private static <T> List<T> rmBase(List<T> list){
		return list.stream().distinct().collect(Collectors.toList());
	}

	/**
	 * 获取list中的某个属性的集合
	 * <p>返回结果需转换类型，例如:</p>
	 * <p>List<String> result= (List<String>)getFieldList(BeanList,"name")</> </p>
	 * @param list 集合
	 * @param fieldName 字段名
	 * @return
	 */
	public static <T> List<?> getFieldList(List<T> list,String fieldName){
		BeanUtils.copyProperties(1,1);
		if(list == null || list.isEmpty()) {return Collections.emptyList();}
		List<Object> resultList = new ArrayList<>();
		try {
			Field field = list.get(0).getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			for(int i=0;i<list.size();i++) {
				Object obj = field.get(list.get(i));
				resultList.add(obj);
			}
		} catch (Exception e) {
			log.debug("属性未找到，或属性作用域问题:{}",e.getMessage());
			return Collections.emptyList();
		}
		return resultList;
	}

	/**
	 * 获取list中的某个属性的集合
	 * @param list 集合
	 * @param paramName 字段名
	 * @return
	 */
	public static <T>List<T> getParamList(List<?> list,String paramName,Class<T> cla){
		List<T> resultList = new ArrayList<T>();
		if(list.isEmpty()) {
			return Collections.emptyList();
		}
		try {
			Field field = list.get(0).getClass().getDeclaredField(paramName);
			field.setAccessible(true);
			for(int i=0;i<list.size();i++) {
				Object obj = field.get(list.get(i));
				resultList.add((T)obj);
			}
		} catch (Exception e) {
			log.debug("属性未找到，或属性作用域问题:{}",e.getMessage());
			return Collections.emptyList();
		}
		return resultList;
	}

//	public static <T>Map<String,?> getFieldList(List<T> list,String fieldName,String fieldValue){
//		Map<String, Object> resultMap = new HashMap<>();
//		BeanUtils.copyProperties(1,1);
//		if(list.isEmpty()) {return Collections.emptyMap();}
//		try {
//			Field field = list.get(0).getClass().getDeclaredField(fieldName);
//			field.setAccessible(true);
//
//			Field field2 = list.get(0).getClass().getDeclaredField(fieldValue);
//			field2.setAccessible(true);
//
//			for(int i=0;i<list.size();i++) {
//				Object obj = field.get(list.get(i));
//				resultMap.put( (String)obj, field2.get(list.get(i)));
//			}
//		} catch (Exception e) {
//			logger.debug("属性未找到，或属性作用域问题");
//			return Collections.emptyMap();
//		}
//		return resultMap;
//	}

	/**
	 * 对list进行排序，list类型为实体对象
	 * @param list 源集合
	 * @param sortField 对象属性
	 * @param isAsc 排序方式,"desc false"或"asc true"
	 * @return
	 */
	public static <T> List<T> sortByBean(List<T> list, final String sortField, final Boolean isAsc){
		Collections.sort(list, new Comparator<T>() {
			public int compare(T a, T b) {
				//默认flag值1，默认是升序，如果返回为-flag则是降序
				int flag= compareObject(sortField, isAsc, a, b);
				if(flag<0){
					return -1;
				}
				if(flag==0){
					return 0;
				}
				return 1;
			}
		});
		return list;
	}

	/**
	 * list多个属性按照一个规则排序
	 * @param list       源集合
	 * @param fieldName  多个属性
	 * @param isAsc 是否升序
	 */
	public static <T> void sort(List<T> list, final boolean isAsc,  final String... fieldName) {
		Collections.sort(list, new Comparator<T>() {
			public int compare(T a, T b) {
				int ret = 0;
				try {
					for (int i = 0; i < fieldName.length; i++) {
						ret = ListUtil.compareObject(fieldName[i], isAsc, a, b);
						if (0 != ret) {
							break;
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return ret;
			}
		});
	}

	/**
	 * 个体每个属性指定排序方式进行排序List
	 * @param list
	 * @param filedNameArr 属性数组
	 * @param sortArr 每个属性对应的升降序数组， true升序，false降序
	 */
	public static <T> void sortByMoreParam(List<T> list, final String[] filedNameArr, final Boolean[] sortArr) {
		if (filedNameArr.length != sortArr.length) {
			throw new RuntimeException("属性数组元素个数和升降序数组元素个数不相等");
		}
		Collections.sort(list, new Comparator<T>() {
			public int compare(T a, T b) {
				int ret = 0;
				try {
					for (int i = 0; i < filedNameArr.length; i++) {
						ret = ListUtil.compareObject(filedNameArr[i], sortArr[i], a, b);
						if (0 != ret) {
							break;
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return ret;
			}
		});
	}

	/**
	 * 去掉重复对象
	 * @param list   集合
	 * @param fieldName   属性名称
	 * @return
	 */
	public static <T> List<T> rmSameByBeanList(List<T> list,String fieldName){
		if(list.isEmpty()) {return Collections.emptyList();}
		try {
			Class<?> clazz = list.get(0).getClass();
			Field field = null;
			field = clazz.getDeclaredField(fieldName);
			field.setAccessible(true);
			int num = list.size();
			List<T> result = new ArrayList<T>(num);
			result.addAll(list);
			for (int i = 0; i < num - 1; i++) {
				for (int j = num - 1; j > i; j--) {
					Object o1  = field.get(list.get(j));
					Object o2  = field.get(list.get(i));
					if( (o1 == null || o2 == null) && (o1 != o2)){
						continue;
					}
					if( (o1 == o2 && o1 == null) || o1.equals(o2) ) {
						result.remove(list.get(i));
					}
				}
			}
			return result;
		}catch(NoSuchFieldException e1){
			log.debug("找不到去重的属性:{}",e1);
		}catch (IllegalAccessException e2) {
			log.debug("找不到该属性:{}",e2);
		}catch(NullPointerException e3) {
			log.debug("属性为Null:{}", e3);
		}
		return list;
	}
	
	/**
	 * 将字符串转换成list
	 * <p>将"1,2,3,4" 转换为list</p>
	 * @param commaArrStr  逗号数组字符串
	 * @return List<String>
	 */
	public static List<String> commaArrToList (String commaArrStr){
		List<String> list = new ArrayList<String>();
		String[] arr = commaArrStr.split(",");
		if(arr.length < 1) {
			return Collections.emptyList();
		}
		for(String s : arr) {
			if(!StringUtils.isBlank(s)) {
				list.add(s);
			}
		}
		return  list;
	}

	/**
	 * 交集
	 * @param listOne	集合1
	 * @param listTwo	集合2
	 * @param <T>
	 * @return
	 */
	private static <T>List<T> intersection(List<T> listOne,List<T> listTwo){
		return listOne.stream().filter(o -> listTwo.contains(o)).collect(Collectors.toList());
	}

	/**
	 * 差集
	 * @param listOne 集合1
	 * @param listTwo 集合2
	 * @param <T>
	 * @return
	 */
	private static <T>List<T> difference(List<T> listOne,List<T> listTwo){
		return listOne.stream().filter(o -> !listTwo.contains(o)).collect(Collectors.toList());
	}

	/**
	 * 并集
	 * <p>若List元素为Bean,则去除对象属性值一致的重复对象<p/>
	 * <p>Arrays.asList()方法的集合直接使用addAll()方法会报错</p>
	 * @param listOne	集合1
	 * @param listTwo	集合2
	 * @param isRmSame	是否去重
	 * @param <T>
	 * @return
	 */
	private static <T>List<T> listAll(List<T> listOne,List<T> listTwo,Boolean isRmSame){
		List<T> collect1 = listOne.parallelStream().collect(Collectors.toList());
		List<T> collect2 = listTwo.parallelStream().collect(Collectors.toList());
		collect1.addAll(collect2);
		if(isRmSame){
			return rmBase(collect1);
		}
		return collect1;
	}

	/**
	 * 并集(不去重)
	 * @param listOne 集合1
	 * @param listTwo 集合2
	 * @param <T>
	 * @return
	 */
	private static <T>List<T> listAll(List<T> listOne,List<T> listTwo){
		return listAll(listOne,listTwo,false);
	}

	//--------------辅助方法-----------
	/**
	 * 对2个对象按照指定属性名称进行排序
	 * @param sortname 属性名称
	 * @param isAsc true升序，false降序
	 * @param a
	 * @param b
	 * @return
	 * @throws Exception
	 */
	private static <T> int compareObject(final String sortname, final boolean isAsc, T a, T b) {
		try {
			int ret;
			Object value1 = ListUtil.forceGetFieldValue(a, sortname);
			Object value2 = ListUtil.forceGetFieldValue(b, sortname);
			String str1 = value1.toString();
			String str2 = value2.toString();
			if (value1 instanceof Number && value2 instanceof Number) {
				int maxlen = Math.max(str1.length(), str2.length());
				str1 = ListUtil.addZero2Str((Number) value1, maxlen);
				str2 = ListUtil.addZero2Str((Number) value2, maxlen);
			} else if (value1 instanceof Date && value2 instanceof Date) {
				long time1 = ((Date) value1).getTime();
				long time2 = ((Date) value2).getTime();
				int maxlen = Long.toString(Math.max(time1, time2)).length();
				str1 = ListUtil.addZero2Str(time1, maxlen);
				str2 = ListUtil.addZero2Str(time2, maxlen);
			}
			if (isAsc) {
				ret = str1.compareTo(str2);
			} else {
				ret = str2.compareTo(str1);
			}
			return ret;
		}catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 给数字对象按照指定长度在左侧补0.
	 * 使用案例: addZero2Str(11,4) 返回 "0011", addZero2Str(-18,6)返回 "-000018"
	 * @param numObj 数字对象
	 * @param length 指定的长度
	 * @return
	 */
	private static String addZero2Str(Number numObj, int length) {
		NumberFormat nf = NumberFormat.getInstance();
		// 设置是否使用分组
		nf.setGroupingUsed(false);
		// 设置最大整数位数
		nf.setMaximumIntegerDigits(length);
		// 设置最小整数位数
		nf.setMinimumIntegerDigits(length);
		return nf.format(numObj);
	}

	/**
	 * 获取指定对象的指定属性值（去除private,protected的限制）
	 * @param obj 属性名称所在的对象
	 * @param fieldName 属性名称
	 * @return
	 * @throws Exception
	 */
	private static Object forceGetFieldValue(Object obj, String fieldName) throws Exception {
		Field field = obj.getClass().getDeclaredField(fieldName);
		Object object = null;
		boolean accessible = field.isAccessible();
		if (!accessible) {
			// 如果是private,protected修饰的属性，需要修改为可以访问的
			field.setAccessible(true);
			object = field.get(obj);
			// 还原private,protected属性的访问性质
			field.setAccessible(accessible);
			return object;
		}
		object = field.get(obj);
		return object;
	}
	//--------------辅助方法-----------End
}